package cn.piesat.scanning.business.common.algorithm.dataUnzip;

import com.alibaba.fastjson.JSON;
import cn.piesat.scanning.business.common.AlgorithmDefineAbstract;
import cn.piesat.scanning.dto.HtPathConfigurationDTO;
import cn.piesat.scanning.dto.HtScheduleJobDTO;
import cn.piesat.scanning.service.DbDmsSchedulerTaskFileRecordService;
import cn.piesat.scanning.service.HtPathConfigurationService;
import cn.piesat.scanning.service.HtScheduleJobService;
import cn.piesat.scanning.utils.FileUtil;
import cn.piesat.scanning.utils.MatchTime;
import cn.piesat.scanning.utils.UnZipUtil;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.filefilter.*;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.io.File;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

/**
 * 数据解压
 * @author xhl
 */
@Component
public class DataUnzip extends AlgorithmDefineAbstract {

    @Autowired
    private HtPathConfigurationService htPathConfigurationService;
    @Autowired
    private HtScheduleJobService htScheduleJobService;
    @Autowired
    private DbDmsSchedulerTaskFileRecordService dbDmsSchedulerTaskFileRecordService;

    @Override
    public void exec(Map<String, Object> params, String taskId) {
        DataUnzipParams dataUnzipParams = JSON.parseObject(JSON.toJSONString(params),DataUnzipParams.class);
        HtScheduleJobDTO taskDTO = htScheduleJobService.findById(taskId);
        HtPathConfigurationDTO pathDTO = htPathConfigurationService.findById(taskDTO.getPathConfigId());
        List<String> dirPath = processParams(pathDTO, dataUnzipParams);
        List<File> fileList = new ArrayList<>();
        for (String path : dirPath) {
            fileList.addAll(listFile(dataUnzipParams,path));
        }
        unZip(fileList,pathDTO.getOutputPath(),taskDTO.getId());
    }

    private void unZip(List<File> fileList, String outputPath, String taskId) {
        if (StringUtils.isEmpty(outputPath)) {
            return;
        }
        dbDmsSchedulerTaskFileRecordService.prepareDataByFileList(taskId,fileList);
        for (File file : fileList) {
            dbDmsSchedulerTaskFileRecordService.dataExecution(taskId,file.getName());
            boolean b = UnZipUtil.checkFileNameType(file, outputPath);
            dbDmsSchedulerTaskFileRecordService.dataResults(taskId,file.getName(),b);
        }
    }

    /**
     * 处理输入参数
     * @param pathDTO 路径实体类，获取扫描路径和输出路径
     * @param dataUnzipParams 要处理的参数（开始时间、结束时间、目录匹配规则、最近多少分钟）
     */
    private List<String> processParams(HtPathConfigurationDTO pathDTO, DataUnzipParams dataUnzipParams) {
        String scanningPath = pathDTO.getScanningPath();
        String startTime = dataUnzipParams.getStartTime();
        String endTime = dataUnzipParams.getEndTime();
        String lately = dataUnzipParams.getLately();
        String dirPathRule = dataUnzipParams.getDirPathRule();
        List<String> dirPath = new ArrayList<>();
        //如果扫描路径为空，则数据扫描自定义算法不继续执行
        if (StringUtils.isNotEmpty(scanningPath)) {
            //填入开始时间和最近多少分钟的两种情况，优先填入开始时间参数
            if (StringUtils.isNotEmpty(startTime)) {
                dataUnzipParams.setStartTime(conventDateTimeFormat(startTime));
                dataUnzipParams.setEndTime(conventDateTimeFormat(endTime));
                String completePathRule = scanningPath + File.separator + dirPathRule;
                if(checkBraces(dirPathRule)) {
                    List<Date> dayList = getTimeZones(dataUnzipParams.getStartTime(), dataUnzipParams.getEndTime());
                    List<String> dirList = new ArrayList<>();
                    for (Date date : dayList) {
                        String pathByDate = FileUtil.getPathByDate(completePathRule,date);
                        if (new File(pathByDate).exists()) {
                            dirList.add(pathByDate);
                        }
                    }
                    dirPath = dirList.stream().distinct().collect(Collectors.toList());
                }else{
                    dirPath = new ArrayList<>();
                    dirPath.add(completePathRule);
                }
            } else if (StringUtils.isNotEmpty(lately)) {
                long late = Long.parseLong(lately);
                DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyyMMddHHmm");
                dataUnzipParams.setStartTime(LocalDateTime.now().minusMinutes(late).format(df));
                dataUnzipParams.setEndTime(LocalDateTime.now().format(df));
                String completePathRule = scanningPath + File.separator + dirPathRule;
                if(checkBraces(dirPathRule)) {
                    String pathByDate = FileUtil.getPathByDate(completePathRule,new Date());
                    dirPath.add(pathByDate);
                }else{
                    dirPath.add(completePathRule);
                }
            }
        }
        return dirPath;
    }

    /**
     * 判断字符串中是否存在 {}
     * @param path
     * @return boolean
     */
    private boolean checkBraces(String path) {
        String leftBraces = "{";
        return path.contains(leftBraces);
    }

    /**
     * 格式化时间
     * @param string
     * @return String datetime
     */
    private String conventDateTimeFormat(String string){
        String dateTime = "";
        DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        DateTimeFormatter df1 = DateTimeFormatter.ofPattern("yyyyMMdd");
        //判断是否为空,空的情况直接获取当前时间 格式 yyyyMMdd
        if(StringUtils.isEmpty(string)) {
            dateTime = LocalDateTime.now().format(df1);
            return dateTime;
        }
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");

        try {
            //格式为 '{yyyy+-}{MM+-}{dd+-}{HH+-}{mm+-}{ss+-}'
            if(checkBraces(string)) {
                Date date = MatchTime.getDate(new Date(), string);
                dateTime = sdf.format(date);
            }else {
                dateTime = LocalDateTime.parse(string, df).format(df1);
            }
        } catch ( Exception e){
            e.printStackTrace();
        }
        return dateTime;
    }

    /**
     * 获取时间区间中所有的天
     * @param startTime
     * @param endTime
     * @return List<Date>
     */
    private List<Date> getTimeZones(String startTime, String endTime){
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
        List<Date> list = new ArrayList<Date>();
        try {
            Date startDate = sdf.parse(startTime);
            Date endDate = sdf.parse(endTime);
            for (long i = (startDate.getTime()-(24*60*60*1000)); i < endDate.getTime(); i++) {
                i += (24*60*60*1000);
                Date date = new Date();
                date.setTime(i);
                list.add(date);
            }
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return list;
    }

    private List<File> listFile(DataUnzipParams params, String scanPath) {
        String fileNamePattern = params.getFileNamePattern();
        String fileDatePattern = params.getFileDatePattern();
        String start = params.getStartTime();
        String end = params.getEndTime();
        int subLength = start.length();
        long s = Long.parseLong(start);
        long e = Long.parseLong(end);
        if (!scanPath.isEmpty()) {
            File dir = new File(scanPath);
            if (!dir.exists() || dir.isFile()) {
                return new ArrayList<>();
            }
            IOFileFilter filter = FileFilterUtils.and(EmptyFileFilter.NOT_EMPTY, new RegexFileFilter(fileNamePattern));
            //扫描速度取决于目标文件夹子目录数
            Collection<File> fileCollection = FileUtils.listFiles(dir, filter, DirectoryFileFilter.INSTANCE);
            return fileCollection.stream().filter(file -> {
                String dateTimeStr = getDateTimeStr(file.getName(), fileDatePattern);
                long date = Long.parseLong(dateTimeStr.length() > subLength ? dateTimeStr.substring(0, subLength) : dateTimeStr);
                /** 判断是否在时间范围内 */
                if (date >= s && date <= e) {
                    return true;
                }
                return false;
            }).collect(Collectors.toList());
        }
        return new ArrayList<>();
    }

    /**
     * 根据正则匹配获取到日期，如果小于12位则补0
     * @param fileName
     * @param dataFilePattern
     * @return
     */
    public String getDateTimeStr(String fileName,String dataFilePattern){
        String str = "";
        if(dataFilePattern != null && !"".equals(dataFilePattern)){
            Pattern p = Pattern.compile(dataFilePattern);
            Matcher m = p.matcher(fileName);
            boolean result = m.find();
            while (result){
                str = m.group(0);
                break;
            }
        }
        if(str.length() < 12){
            int leftlenth = 12 - str.length();
            for(int i = 0 ; i < leftlenth ; i++){
                str += "0";
            }
        }
        return str;
    }
}
